#!/usr/bin/python
# pylint: disable-msg = W0102
'''
Created by Colin Gillespie <c.gillespie@ncl.ac.uk>
$LastChangedDate$

'''
from __future__ import division

__revision__ = '$Rev$'
from sympy import Symbol


from GlobalVariables import globalVariables
from sympy import Symbol
#import MomentCumulantConversion as MCC
from OutputFormat import *#getOutput
from Singleton import Singleton

from ClosureMethods import getMethod


class Variables(Singleton):

    def __init__(self):
        
        self.output = getOutput()
        self.closure = getMethod()
        self.mom2cum = {}
        self.cum2mom = {}
        self.vars = {}
        #self.cum_vars = cum_vars
        
    def getMoment(self, value, moment=True):
        print value
        if moment:
            if self.vars.has_key(value):
                return self.vars[value]
            
            if sum(value) <= globalVariables()['closure_order']:
                self.vars[value] = self.output.convert(value)
                return self.vars[value]
            else:
                self.vars[value] = self.closure.closeMoment(value)
                return self.vars[value]
                
        else:
            if not self.cum2mom.has_key(value):
                self.cum2mom[value] = self.closure.closeCumulant(value)
            return self.cum2mom[value]
    
    def getCumulant(self, value, moment=True):
        if not moment:
            #print 'hi1'
            if sum(value) > globalVariables()['closure_order']:
                return 0
            elif self.cum2mom.has_key(value):
                return self.cum2mom[value]
            else:
                kappa = self.output.convert(value)
                self.cum2mom[value] = kappa
                return self.cum2mom[value]

        else:
            if self.mom2cum.has_key(value):
                return self.mom2cum[value]
            else:            
                kappa = self.closure.closeMomentAsCumulant(value)
                print 'kappa', kappa
                self.mom2cum[value] = kappa
                return self.mom2cum[value]
    
    def getDifferential(self, value):
        diff = self.output.getDifferential(value)
        return diff
    
    def initialise(self):
        self.mom2cum.clear()
        self.cum2mom.clear() 
        self.vars.clear()
        self.closure.initialise() 


class TimeVariables(Singleton):
    '''When the function is rational, we may apply a different closure level to variables that
        have been differentiated wrt to time.
        
        For example, we may set:
        
            diff(E_x_x(t),t) =0 , but not E_x_x(t)
    '''
    
    
    def __init__(self):
        
        self.output = getOutput()
        self.closure = getMethod(time=True)
        self.mom2cum = {}
        self.cum2mom = {}
        self.vars = {}
        #self.cum_vars = cum_vars
        
    def getMoment(self, value, moment=True):
        if moment:
            if self.vars.has_key(value):
                return self.vars[value]
            
            if sum(value) <= globalVariables()['time_closure_order']:
                self.vars[value] = self.output.convert(value)
                return self.vars[value]
            else:
                self.vars[value] = self.closure.closeMoment(value)
                return self.vars[value]
                
        else:
            if not self.cum2mom.has_key(value):
                self.cum2mom[value] = self.closure.closeCumulant(value)
            return self.cum2mom[value]
    
    def getCumulant(self, value, moment=True):
        if not moment:
            #print 'hi1'
            if sum(value) > globalVariables()['time_closure_order']:
                return 0
            elif self.cum2mom.has_key(value):
                return self.cum2mom[value]
            else:
                kappa = self.output.convert(value)
                self.cum2mom[value] = kappa
                return self.cum2mom[value]

        else:
            if self.mom2cum.has_key(value):
                return self.mom2cum[value]
            else:            
                kappa = self.closure.closeMomentAsCumulant(value)
                print 'kappa', kappa
                self.mom2cum[value] = kappa
                return self.mom2cum[value]
    
    def getDifferential(self, value):
        diff = self.output.getDifferential(value)
        return diff
    
    def initialise(self):
        self.mom2cum.clear()
        self.cum2mom.clear() 
        self.vars.clear()
        self.closure.initialise() 







